﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace PersonEntity
{
    public class handleClinet
    {
        IFormatter formatter = new BinaryFormatter();
        Socket clientSocket;
        iDS DS;
        NetworkStream networkStream;
        public DS_NET_Server Server;
        Thread ctThread;
        string flag = string.Empty;

        public void startClient(Socket inClientSocket, iDS ds)
        {
            this.clientSocket = inClientSocket;
            this.DS = ds;
            this.networkStream = new NetworkStream(clientSocket);
            ctThread = new Thread(doChat);
            ctThread.Start();
            Thread CheckConnection = new Thread(ConnectionCheck);
            CheckConnection.Start();
        }

        private void doChat()
        {
            byte[] bytesFrom = new byte[(int)clientSocket.ReceiveBufferSize];
            int dataLenght = clientSocket.Available;
            string dataFromClient = null;

            while ((clientSocket.Connected))
            {                
                try
                {
                    networkStream = new NetworkStream(clientSocket);
                    
                    if (networkStream.DataAvailable)
                    {
                        

                        if (flag == string.Empty)
                        {

                            networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
                            dataFromClient = System.Text.Encoding.UTF8.GetString(bytesFrom);
                            dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("\n"));
                            dataFromClient = dataFromClient.Replace("\r", "");
                            string[] tempStr = dataFromClient.Split('^');

                            switch (tempStr[0])
                            {
                                case "load": this.LoadRequest();
                                    break;
                                case "create": this.CreateRequest(tempStr[1]);
                                    break;
                                case "read": this.ReadRequest(Convert.ToInt32(tempStr[1]));
                                    break;
                                case "delete": this.DeleteRequest(Convert.ToInt32(tempStr[1]));
                                    break;
                                case "update": flag = "update";
                                    RespondOk();
                                    break;
                                default: break;
                            }
                        }
                        else
                        {
                            switch (flag)
                            {
                                case "update": BinaryObject(networkStream);
                                    flag = string.Empty;
                                    break;
                                default: break;
                            }
                        }                      
                    }


                }
                catch (System.Threading.ThreadAbortException lException)
                {
                    Console.WriteLine(lException.Message);
                }
                catch
                {
                    CloseConnection();
                }
            }
        }

        private void BinaryObject(Stream stream)
        {
            
            Person p = (Person)formatter.Deserialize(stream);
            DS.Update(p);
            RespondOk();
        }


        private void SiteRequest(string dataFromClient)
        {
            byte[] outStream = File.ReadAllBytes(dataFromClient);
            clientSocket.SendBufferSize = 20000;
            networkStream.Write(outStream, 0, outStream.Length);
            networkStream.Flush();
        }



        private void CreateRequest(string str)
        {
            string[] tempArr = str.Split(',');
            Person p = new Person();
            
            DS.Create(p);
            RespondOk();
        }

        private void UpdateRequest(int ID, string str)
        {

            string[] tempArr = str.Split(',');
            Person p = new Person();
            
            DS.Update(p);
            RespondOk();
        }

        private void ReadRequest(int ID)
        {
            Person p = DS.Read(ID);
            string strP = "No such ID";
            if (p != null)
            {
                
            }
            byte[] outStream = System.Text.Encoding.UTF8.GetBytes(strP + "\n");
            networkStream.Write(outStream, 0, outStream.Length);
            networkStream.Flush();
        }

        private void DeleteRequest(int ID)
        {
            DS.Delete(ID);
            RespondOk();
        }

        private void LoadRequest()
        {

            List<Person> pList = DS.Load();

            IFormatter formatter = new BinaryFormatter();
            formatter.Serialize(networkStream, pList);
            networkStream.Flush();
        }

        private void RespondOk()
        {
            byte[] outStream = System.Text.Encoding.UTF8.GetBytes("ok" + "\n");
            networkStream.Write(outStream, 0, outStream.Length);
            networkStream.Flush();
        }


        private void CloseConnection()
        {
            clientSocket.Close();
            Thread.CurrentThread.Abort();
        }

        private void ConnectionCheck()
        {
            while (true)
            {
                if (!clientSocket.Connected)
                {
                    ctThread.Abort();
                    Thread.CurrentThread.Abort();
                }
                System.Threading.Thread.Sleep(20000);
            }
        }
    }
}
